#pragma once

#include <SCSlotHeader.h>
#include <SCItemSlot.h>
#include <SCSlotContainer.h>

class Player;

class SlotManager
{
	friend class ItemManager;
	friend class SkillManager;
	friend class QuickManager;
	friend class QuickStyleManager;
public:
	SlotManager(void);
	~SlotManager(void);

	VOID				Init( Player * pPlayer );
	VOID				Release();
	
	SCSlotContainer *	GetSlotContainer( SLOTIDX Index );

	template <class FUNCTOR>
	BOOL				ForeachSlot( SLOTIDX idx, FUNCTOR & opr );
	template <class FUNCTOR>
	BOOL				Foreach( SLOTIDX idx, FUNCTOR & opr );

	BOOL				IsEmpty( SLOTIDX Index, POSTYPE pos );
	BOOL				ValidState();
private:
	BOOL				ValidPos( SLOTIDX atIndex, POSTYPE atPos, BOOL bEmptyCheck = TRUE );
	BOOL				ValidContainer( SLOTIDX AtIndex );
	
private:
	SCSlotContainer	*	m_pSlotContainer[SI_MAX];
	Player *			m_pPlayer;
};


template <class FUNCTOR>
BOOL SlotManager::ForeachSlot( SLOTIDX idx, FUNCTOR & opr )
{
	SCSlotContainer * pContainer = GetSlotContainer( idx );
	for( POSTYPE i = 0 ; i < pContainer->GetMaxSlotNum() ; ++i )
	{
		if( !pContainer->IsEmpty(i) )
		{
			SCSlot & slot = pContainer->GetSlot(i);

			if( opr(pContainer,slot) ) return TRUE;
		}
	}
	return FALSE;
}

template <class FUNCTOR>
BOOL SlotManager::Foreach( SLOTIDX idx, FUNCTOR & opr )
{
	SCSlotContainer * pContainer = GetSlotContainer( idx );
	for( POSTYPE i = 0 ; i < pContainer->GetMaxSlotNum() ; ++i )
	{
		if( opr(pContainer,i) ) return TRUE;
	}
	return FALSE;
}

class DeleteItem
{
	CODETYPE m_code;
	POSTYPE  m_max_num;
public:
	DeleteItem(CODETYPE code, POSTYPE max_num):
	  m_max_num(max_num),m_code(code){}
	  ~DeleteItem(){}

	BOOL operator()( SCSlotContainer * pContainer, SCSlot & rSlot )
	{
		SCItemSlot & rItemSlot = (SCItemSlot &)rSlot;
		if( m_code == rSlot.GetCode() )
		{
			if( m_max_num < rSlot.GetNum() )
			{
				//pContainer->UpdateSlot( rSlot.GetPos(), ST_NONE,0,0,0,rSlot.GetDura()-m_max_num,0, UB_DURA );
				rSlot.SetNum( rSlot.GetNum()-m_max_num );
				return TRUE;
			}
			m_max_num -= rSlot.GetNum();
			pContainer->DeleteSlot( rSlot.GetPos(), NULL );

			if( 0 == m_max_num ) return TRUE;
		}

		return FALSE;
	}
};

class EmptyItemCheck
{
	CODETYPE m_code;
	POSTYPE  m_max_num;
public:
	EmptyItemCheck(CODETYPE code, POSTYPE max_num):
	  m_max_num(max_num),m_code(code){}
	  ~EmptyItemCheck(){}

	  BOOL operator()( SCSlotContainer * pContainer, SCSlot & rSlot )
	  {
		  SCItemSlot & rItemSlot = (SCItemSlot &)rSlot;
		  if( m_code == rSlot.GetCode() )
		  {
			  if( m_max_num <= rSlot.GetNum() ) return TRUE;
			  m_max_num -= rSlot.GetNum();
			  /*
			  if( rItemSlot.IsOverlap() )
			  {
				  
			  }
			  else
			  {
				  --m_max_num;
				  if( m_max_num == 0 ) return TRUE;
			  }
			  */
		  }

		  return FALSE;
	  }

};

class OverlappedItemCheck
{
	CODETYPE m_code;
	POSTYPE  m_max_num;
public:
	OverlappedItemCheck(CODETYPE code, POSTYPE num):
	  m_max_num(num),m_code(code){}
	  ~OverlappedItemCheck(){}

	  VOID SetNum( POSTYPE num ) { m_max_num = num;	}
	  BOOL operator()( SCSlotContainer * pContainer, SCSlot & rSlot )
	  {
		  SCItemSlot & rItemSlot = (SCItemSlot &)rSlot;
		  if( m_code == rItemSlot.GetCode() )
		  {
			  if( rItemSlot.IsOverlap() )
			  {
				if( m_max_num + rItemSlot.GetNum() <= rItemSlot.GetMaxNum() )
					return TRUE;
				m_max_num = rItemSlot.GetMaxNum() - rItemSlot.GetNum();
				if( m_max_num == 0 ) return TRUE;
			  }
		  }
		  return FALSE;
	  }
};
